export class List<T> {
  /**
   * @description: 内部数据
   * @private
   * @type {Array<T>}
   */
  private _data: T[] = [];

  /**
   * @description: 构造函数
   * @param {Array<T>} array 初始数据
   * @returns
   */
  constructor(array?: T[]) {
    this._data = array ?? [];
  }

  /**
   * @description: 添加元素
   * @param {T} data 元素
   * @returns
   */
  add(data: T): void {
    this._data = Array.from(new Set([...this._data, data]));
  }

  /**
   * @description: 添加全部元素
   * @param {Array<T>} data 元素
   * @returns
   */
  addAll(data: T[]): void {
    this._data = Array.from(new Set([...this._data, ...data]));
  }

  /**
   * @description: 是否包含元素
   * @param {T} data 元素
   * @returns {boolean}
   */
  contains(data: T): boolean {
    if (data === undefined || data === null) {
      return false;
    }
    return this._data.includes(data);
  }

  /**
   * @description: 是否包含元素
   * @param {T} data 元素
   * @returns
   */
  remove(data: T): void {
    this._data = this._data.filter((item) => item !== data);
  }

  /**
   * @description: 是否包含元素
   * @param {Array<T>} data 元素
   * @returns
   */
  removeAll(data: T[]): void {
    this._data = this._data.filter((item) => !data.includes(item));
  }

  /**
   * @description: 清空
   * @private
   * @returns
   */
  clear(): void {
    this._data = [];
  }

  /**
   * @description: 遍历
   * @param {Function} callback 回调函数
   * @returns
   */
  forEach(callback: (item: T, index: number, list: List<T>) => void): void {
    this._data.forEach((item, index) => {
      callback.call(null, item, index, this);
    });
  }

  /**
   * @description: 遍历
   * @param {Function} callback 回调函数
   * @returns
   */
  filter(callback: (item: T, index: number, list: List<T>) => boolean): void {
    this._data = this._data.filter((item, index) =>
      callback.call(null, item, index, this)
    );
  }

  /**
   * @description: 遍历
   * @param {Function} callback 回调函数
   * @returns
   */
  map(
    callback: (item: T, index: number, list: List<T>) => any
  ): List<ReturnType<typeof callback>> {
    return new List<ReturnType<typeof callback>>(
      this._data.map((item, index) => callback.call(null, item, index, this))
    );
  }

  /**
   * @description: 转换为数组
   * @returns {Array<T>}
   */
  toArray(): T[] {
    return [...this._data];
  }
}
